#Python中的命名空间是什么？

#名称（也称为标识符）只是赋予对象的名称。Python中的一切都是对象。名称是访问基础对象的一种方式。
#例如，当我们执行赋值操作时a = 2，2是一个存储在内存中的对象，而a是与之关联的名称。我们可以通过内置函数 获取某些对象的地址（在RAM中）id()。让我们看看如何使用它。

# 注意:您可能会得到不同的id值
a = 2
print('id(2) =', id(2))
print('id(a) =', id(a))

#在这里，两者都引用相同的对象2，因此它们具有相同的id()。让我们做些有趣的事情。

a = 2
print('id(a) =', id(a))

a = a+1
print('id(a) =', id(a))

print('id(3) =', id(3))

b = 2
print('id(b) =', id(b))
print('id(2) =', id(2))

#最初，创建一个对象2并将名称a与之相关联，当我们执行a = a + 1时，将创建一个新的对象3，现在a与该对象相关联。
#请注意，id（a）和id（3）具有相同的值。
#此外，当执行b = 2时，新名称b与先前的对象2相关联。
#这是有效的，因为Python不必创建新的重复对象。 名称绑定的这种动态特性使Python变得功能强大。 名称可以引用任何类型的对象。

def printHello():
    print("Hello")


a = printHello

a()

"""什么是Python中的命名空间？"""

#命名空间是名称的集合。
#在Python中，您可以将命名空间想象为已定义的每个名称到对应对象的映射。
#不同的命名空间可以在给定时间共存，但完全隔离。
#当我们启动Python解释器时，将创建一个包含所有内置名称的命名空间，并且只要该解释器运行，该命名空间就会存在。
#这就是为什么内置的功能（例如id()）print()等始终可以从程序的任何部分使用的原因。每个模块创建自己的全局命名空间。
#这些不同的命名空间是隔离的。因此，不同模块中可能存在的相同名称不会冲突。
#模块可以具有各种功能和类。调用函数时会创建一个本地命名空间，其中定义了所有名称。与类相似。下图可能有助于阐明这一概念。

"""Python变量作用域"""

#尽管定义了各种唯一的命名空间，但我们可能无法从程序的每个部分访问它们。作用域的概念开始起作用。
#作用域是程序的一部分，从那里可以直接访问命名空间而无需任何前缀。
#在任何给定时刻，至少有三个嵌套作用域。
#具有本地名称的当前函数的作用域
#具有全局名称的模块的作用域
#具有内置名称的最外部作用域
#在函数内部进行引用时，将在本地命名空间中搜索名称，然后在全局命名空间中搜索，最后在内置命名空间中搜索。
#如果另一个函数内有一个函数，则新作用域嵌套在本地作用域内。

def outer_function():
    b = 20
    def inner_func():
        c = 30

a = 10

#在这里，变量a在全局命名空间中。变量b在的本地命名空间中，outer_function()而c在的嵌套本地命名空间中inner_function()。
#当我们在时inner_function()，c在我们本地，b在非本地，a在全局。我们可以为c读取和分配新值，但只能 从中读取b和ainner_function()。
#如果我们尝试分配作为值b，一个新的变量b在本地命名空间比非本地不同的创建b。当我们分配一个值，同样的事情发生一个。
#但是，如果我们将a声明为全局a，则所有引用和赋值都将移至全局a。同样，如果我们想重新绑定变量b，则必须将其声明为非本地变量。以下示例将进一步阐明这一点。

def outer_function():
    a = 20

    def inner_function():
        a = 30
        print('a =', a)

    inner_function()
    print('a =', a)


a = 10
outer_function()
print('a =', a)

#在此程序中，在不同的命名空间中定义了三个不同的变量a并进行了相应的访问。


def outer_function():
    global a
    a = 20

    def inner_function():
        global a
        a = 30
        print('a =', a)

    inner_function()
    print('a =', a)


a = 10
outer_function()
print('a =', a)

#在这里，由于使用了关键字global，所以所有引用和赋值都指向全局a。